package edu.nf.project.services.storeOperation.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import edu.nf.project.entitys.entity.storeOperation.convention.operate.Board;
import edu.nf.project.entitys.entity.storeOperation.convention.operate.CustomerOrder;
import edu.nf.project.entitys.enums.storeOperation.BoardStatusEnum;
import edu.nf.project.entitys.enums.storeOperation.OrderStatusEnum;
import edu.nf.project.mappers.storeOperation.convention.BoardMapper;
import edu.nf.project.mappers.storeOperation.convention.CustomerOrderMapper;
import edu.nf.project.services.exception.derivedAnomalies.CustomerOrderException;
import edu.nf.project.services.storeOperation.BoardService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;

/**
 * 餐桌Service实现类
 */
@Service
public class BoardServiceImpl implements BoardService {
    @Autowired
    private BoardMapper boardMapper;
    
    @Autowired
    private CustomerOrderMapper customerOrderMapper;

    @Override
    public List<Board> getTargetBoardList(Integer[] regionIds) {
        LambdaQueryWrapper<Board> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Board::getRegionId, Arrays.asList(regionIds));
        return boardMapper.selectList(wrapper);
    }

    @Override
    public Board getBoardById(Integer boardId) {
        Board board = boardMapper.selectById(boardId);
        if (board.getBoardStatus() == BoardStatusEnum.UNINHABITED){
            return board;
        }
        throw new CustomerOrderException(50001,
                "餐桌"+BoardStatusEnum.getMessageByDescription(board.getBoardStatus().getDescription())
                +"，请重新扫码");
    }

    @Override
    public Boolean addBoard(Board board) {
        return boardMapper.insert(board) > 0;
    }

    @Override
    public Boolean updBoard(Board board) {
        return boardMapper.updateById(board) > 0;
    }

    @Override
    public Boolean delBoard(Integer boardId) {
        Board board = new Board();
        board.setBoardId(boardId);
        return boardMapper.deleteById(board) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean changeBoard(Integer boardId, Integer orderId) {
        // 1. 检查新餐桌是否可用
        Board newBoard = boardMapper.selectById(boardId);
        if (newBoard == null) {
            throw new CustomerOrderException(50002, "目标餐桌不存在");
        }
        if (newBoard.getBoardStatus() != BoardStatusEnum.UNINHABITED) {
            throw new CustomerOrderException(50001, "目标餐桌已被占用，无法更换");
        }

        // 2. 获取当前订单信息，找到原餐桌
        CustomerOrder order = customerOrderMapper.selectById(orderId);
        if (order == null) {
            throw new CustomerOrderException(50003, "订单不存在");
        }
        
        // 3. 检查订单状态
        if (order.getOrderStatus() == OrderStatusEnum.CANCELED) {
            throw new CustomerOrderException(50004, "已取消的订单不能更换餐桌");
        }
        
        Integer oldBoardId = order.getBoardId();
        Board oldBoard = boardMapper.selectById(oldBoardId);
        if (oldBoard == null) {
            throw new CustomerOrderException(50002, "原餐桌不存在");
        }

        // 4. 更新订单的餐桌ID
        LambdaUpdateWrapper<CustomerOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(CustomerOrder::getOrderId, orderId)
                    .set(CustomerOrder::getBoardId, boardId);
        
        int result = customerOrderMapper.update(null, updateWrapper);
        if (result <= 0) {
            throw new CustomerOrderException(50003, "订单更新失败");
        }

        // 5. 更新餐桌状态
        // 5.1 更新新餐桌状态为已占用
        newBoard.setBoardStatus(BoardStatusEnum.REPAST);
        boardMapper.updateById(newBoard);

        // 5.2 更新原餐桌状态为空闲
        oldBoard.setBoardStatus(BoardStatusEnum.UNINHABITED);
        boardMapper.updateById(oldBoard);

        return true;
    }
}
